Skip to content

fix(send): classify tree buffers by filetype only (#289)#292

Merged
ThomasK33 merged 2 commits into
mainfrom
fix/289-tree-bufname-misclassification
Jun 22, 2026
Merged

fix(send): classify tree buffers by filetype only (#289)#292
ThomasK33 merged 2 commits into
mainfrom
fix/289-tree-bufname-misclassification

Conversation

@ThomasK33

Copy link
Copy Markdown
Member

Summary

Fixes #289.

ClaudeCodeSend classified the current buffer as a file-explorer ("tree") buffer using a substring match against the buffer name (the file's absolute path) in addition to the filetype, in both handle_send_normal and handle_send_visual:

or string.match(current_bufname, "neo%-tree")
or string.match(current_bufname, "NvimTree")
or string.match(current_bufname, "minifiles://")

So an ordinary filetype=lua file whose path merely contained neo-tree or NvimTree (e.g. a plugin spec named _neo-tree_.lua) was treated as a tree buffer and the send was misrouted into tree-extraction, failing with:

  • visual path (<leader>as<cmd>ClaudeCodeSend<cr>): ClaudeCodeSend_visual->TreeAdd: Not in visual mode (current mode: n)
  • range path (:'<,'>ClaudeCodeSend): ClaudeCodeSend->TreeAdd: Not in a supported tree buffer (current filetype: lua)

Why this is the right fix

The two downstream extractors — integrations.get_selected_files_from_tree() and visual_commands.get_tree_state() — already classify by filetype only. A buffer matched as a tree purely via its name therefore could never extract anything; the substring checks only ever diverted a normal selection into a failing branch.

Every supported explorer sets a distinctive filetype that those extractors key on (neo-tree, NvimTree, oil, minifiles, netrw), so removing the name checks does not regress any of them. In particular, mini.files sets filetype=minifiles in addition to its minifiles:// buffer name, so the minifiles:// branch is redundant (and was never a cause of this bug — a real path cannot contain ://).

Changes

  • lua/claudecode/init.lua: classify by filetype only in both handle_send_normal and handle_send_visual; drop the now-unused current_bufname locals and the redundant minifiles:// discriminator.
  • tests/unit/tree_buffer_classification_spec.lua: new regression spec that drives the real predicate (the existing tree_send_visual_spec mocks the wrapper, so the predicate was untested). Verified two-sided: fails on the old code, passes on the fix.
  • scripts/repro_issue_289.lua: headless reproduction (exit 1 = bug present, 0 = fixed).
  • fixtures/issue-289/: interactive reproduction fixture (affected + control files, :ReproState/:ReproDump helpers).

Verification

  • mise run all — format + lint + 663 tests pass.
  • nvim --headless -u NONE -l scripts/repro_issue_289.lua — exits 0 on this branch (1 on main).
  • Reproduced live with the README-default <leader>as mapping before/after the fix.

Follow-ups (out of scope, noted for tracking)

  • snacks_picker_list is present in handle_send_normal but missing from handle_send_visual, and there is no snacks branch in get_tree_state/get_files_from_visual_selection — visual-mode snacks-picker send is currently unsupported (needs end-to-end work).
  • Tree-buffer classification is duplicated across four sites; a shared helper would prevent future drift.

🤖 Generated with Claude Code

ClaudeCodeSend classified the current buffer as a file-explorer ("tree")
buffer using a substring match against the buffer NAME (the absolute path)
in addition to the filetype:

    or string.match(current_bufname, "neo%-tree")
    or string.match(current_bufname, "NvimTree")
    or string.match(current_bufname, "minifiles://")

So an ordinary filetype=lua file whose path merely contained "neo-tree" or
"NvimTree" (e.g. a plugin spec named _neo-tree_.lua) was treated as a tree
buffer and the send was routed into tree-extraction, failing with:

  - visual path:  ClaudeCodeSend_visual->TreeAdd: Not in visual mode (current mode: n)
  - range path:   ClaudeCodeSend->TreeAdd: Not in a supported tree buffer (current filetype: lua)

The downstream extractors (integrations.get_selected_files_from_tree and
visual_commands.get_tree_state) classify by filetype only, so a name-only
match could never extract anything -- these checks only ever diverted a
normal selection into a failing branch. Every supported explorer
(neo-tree/NvimTree/oil/minifiles/netrw) sets a distinctive filetype, and
mini.files sets filetype=minifiles in addition to its minifiles:// buffer
name, so dropping the substring checks does not regress any of them.

Fix: classify by filetype only in both handle_send_normal and
handle_send_visual, and drop the now-unused current_bufname locals and the
redundant minifiles:// branch.

Adds tests/unit/tree_buffer_classification_spec.lua, which drives the real
predicate (the existing tree_send_visual_spec mocks the wrapper, so the
predicate was untested), plus a headless repro (scripts/repro_issue_289.lua)
and fixture (fixtures/issue-289/).

Change-Id: I2e192c2b63509cd8a29d536f036f259610d1623a
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@ThomasK33

Copy link
Copy Markdown
Member Author

@claude review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9ce3ae551a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread fixtures/issue-289/init.lua Outdated
…roState

Codex review feedback: on the fixed branch the fixture's :ReproState helper
still computed is_tree_buffer via the old "filetype OR bufname-substring"
logic, so verifying the fix with the documented helper showed a misleading
is_tree_buffer=true. ReproState now reports the plugin's current filetype-only
predicate as is_tree_buffer, and exposes the pre-#289 path-substring match as a
separate `legacy_path_substring_match` diagnostic field. README updated to match.

Change-Id: I4f718dfe7d8ca85f1bbb5366456dd22b1c7f296d
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Thomas Kosiewski <tk@coder.com>
@ThomasK33

Copy link
Copy Markdown
Member Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Can't wait for the next one!

Reviewed commit: 1308f1cf8d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@ThomasK33 ThomasK33 added this pull request to the merge queue Jun 22, 2026
Merged via the queue into main with commit 6b4cabc Jun 22, 2026
4 checks passed
@ThomasK33 ThomasK33 deleted the fix/289-tree-bufname-misclassification branch June 22, 2026 14:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] ClaudeCodeSend misclassifies regular buffers as tree buffers when file path contains "neo-tree" or "NvimTree"

1 participant